home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 93 / applic / sdbscn.c < prev    next >
C/C++ Source or Header  |  1987-01-15  |  14KB  |  627 lines

  1. /* SDB - token scanning routines */
  2.  
  3. #include "sdbio.h"
  4.  
  5. int dbv_token;                /* current token */
  6. int dbv_tvalue;                /* integer token value */
  7. char dbv_tstring[STRINGMAX+1];        /* string token value */
  8. struct ifile *dbv_ifp;            /* indirect file context */
  9. struct macro *dbv_macros;        /* macro definitions */
  10. int dbv_fold;                /* case fold alpha comparisons */
  11.  
  12. static char *iprompt,*cprompt;        /* input prompts */
  13. static char cmdline[LINEMAX+2],*lptr;    /* current line and pointer */
  14. static int atbol;            /* flag indicating at bol */
  15. static int savech;            /* lookahead character */
  16. static int savetkn;            /* lookahead token */
  17. static char *keywords[] = {        /* keyword table */
  18.     "ascending",
  19.     "by",
  20.     "char",
  21.     "compress",
  22.     "create",
  23.     "define",
  24.     "delete",
  25.     "descending",
  26.     "exit",
  27.     "export",
  28.     "extract",
  29.     "from",
  30.     "help",
  31.     "insert",
  32.     "import",
  33.     "into",
  34.     "num",
  35.     "print",
  36.     "select",
  37.     "set",
  38.     "show",
  39.     "sort",
  40.     "update",
  41.     "using",
  42.     "where",
  43.     NULL
  44. };
  45. static int keytokens[] = {        /* token values for each keyword */
  46.     ASCENDING,
  47.     BY,
  48.     CHAR,
  49.     COMPRESS,
  50.     CREATE,
  51.     DEFINE,
  52.     DELETE,
  53.     DESCENDING,
  54.     EXIT,
  55.     EXPORT,
  56.     EXTRACT,
  57.     FROM,
  58.     HELP,
  59.     INSERT,
  60.     IMPORT,
  61.     INTO,
  62.     NUM,
  63.     PRINT,
  64.     SELECT,
  65.     SET,
  66.     SHOW,
  67.     SORT,
  68.     UPDATE,
  69.     USING,
  70.     WHERE,
  71.     NULL
  72. };
  73.  
  74. /* db_sinit - initialize the scanner */
  75. db_sinit()
  76. {
  77.     /* at beginning of line */
  78.     atbol = TRUE;
  79.  
  80.     /* make the command line null */
  81.     lptr = NULL;
  82.  
  83.     /* no lookahead yet */
  84.     savech = EOS;
  85.     savetkn = 0;
  86.  
  87.     /* no indirect command files */
  88.     dbv_ifp = NULL;
  89.  
  90.     /* no macros defined */
  91.     dbv_macros = NULL;
  92.  
  93.     /* fold alpha comparisons */
  94.     dbv_fold = TRUE;
  95. }
  96.  
  97. /* db_prompt(ip,cp) - initialize prompt strings */
  98. db_prompt(ip,cp)
  99.   char *ip,*cp;
  100. {
  101.     /* save initial and continuation prompt strings */
  102.     iprompt = ip;
  103.     cprompt = cp;
  104. }
  105.  
  106. /* db_scan(fmt,args) - initiate line scan command parsing */
  107. db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
  108. {
  109.     /* convert the command line and arguments */
  110.     sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
  111.  
  112.     /* start at the beginning of the command line */
  113.     lptr = cmdline;
  114.     iprompt = NULL;
  115.     dbv_ifp = NULL;
  116.  
  117.     /* no lookahead yet */
  118.     savech = EOS;
  119.     savetkn = 0;
  120.  
  121.     /* fold alpha comparisons */
  122.     dbv_fold = TRUE;
  123. }
  124.  
  125. /* db_flush - flush the current input line */
  126. int db_flush()
  127. {
  128.     while (savech != '\n')
  129.         if (savech > ' ')
  130.             return (db_ferror(SYNTAX));
  131.         else
  132.             savech = getchx();
  133.  
  134.     savech = EOS;
  135.     atbol = TRUE;
  136.     return (TRUE);
  137. }
  138.  
  139. /* db_gline - get a line from the current input */
  140. char *db_gline(buf)
  141.   char *buf;
  142. {
  143.     int ch,i;
  144.  
  145.     for (i = 0; (ch = getch()) != '\n' && ch != -1; )
  146.         if (i < LINEMAX)
  147.             buf[i++] = ch;
  148.         else {
  149.             printf("*** line too long ***\nRetype> ");
  150.             i = 0;
  151.         }
  152.     buf[i] = EOS;
  153.  
  154.     return (buf);
  155. }
  156.  
  157. /* db_ifile - setup an indirect command file */
  158. int db_ifile(fname)
  159.   char *fname;
  160. {
  161.     struct ifile *new_ifp;
  162.  
  163.     if ((new_ifp = (struct ifile *)malloc(sizeof(struct ifile))) == NULL)
  164.     return (db_ferror(INSMEM));
  165.     else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) {
  166.     free(new_ifp);
  167.     return (db_ferror(INDFNF));
  168.     }
  169.     new_ifp->if_mtext = NULL;
  170.     new_ifp->if_savech = savech;
  171.     new_ifp->if_lptr = lptr;
  172.     new_ifp->if_next = dbv_ifp;
  173.     dbv_ifp = new_ifp;
  174.  
  175.     /* return successfully */
  176.     return (TRUE);
  177. }
  178.  
  179. /* db_kill - kill indirect command file input */
  180. db_kill()
  181. {
  182.     struct ifile *old_ifp;
  183.  
  184.     while ((old_ifp = dbv_ifp) != NULL) {
  185.         dbv_ifp = old_ifp->if_next;
  186.         if (old_ifp->if_fp != NULL)
  187.             fclose(old_ifp->if_fp);
  188.         savech = old_ifp->if_savech;
  189.         lptr = old_ifp->if_lptr;
  190.     free(old_ifp);
  191.     }
  192.  
  193.     while (savech != '\n')
  194.         savech = getchx();
  195.  
  196.     savech = EOS;
  197.     savetkn = 0;
  198.     atbol = TRUE;
  199. }
  200.  
  201. /* db_token - return the current input token */
  202. int db_token()
  203. {
  204.     struct macro *mptr;
  205.     struct ifile *new_ifp;
  206.  
  207.     /* find a token that's not a macro call */
  208.     while (db_xtoken() == ID) {
  209.  
  210.         /* check for a macro call */
  211.         for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
  212.             if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
  213.             if ((new_ifp = (struct ifile *)malloc(sizeof(struct ifile))) == NULL)
  214.                 printf("*** error expanding macro: %s ***\n",dbv_tstring);
  215.             else {
  216.                 new_ifp->if_fp = NULL;
  217.                 new_ifp->if_mtext = mptr->mc_mtext->mt_next;
  218.             new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
  219.                 new_ifp->if_savech = savech; savech = EOS;
  220.                 new_ifp->if_next = dbv_ifp;
  221.                 dbv_ifp = new_ifp;
  222.             }
  223.             savetkn = 0;
  224.             break;
  225.             }
  226.  
  227.         if (mptr == NULL)
  228.             break;
  229.     }
  230.  
  231.     return (dbv_token);
  232. }
  233.  
  234. /* db_xtoken - return the current input token */
  235. int db_xtoken()
  236. {
  237.     int ch;
  238.  
  239.     /* check for a saved token */
  240.     if ((dbv_token = savetkn) != 0)
  241.     return (dbv_token);
  242.  
  243.     /* get the next non-blank character */
  244.     ch = nextch();
  245.  
  246.     /* check type of character */
  247.     if (isalpha(ch))            /* identifier or keyword */
  248.     get_id();
  249.     else if (isdigit(ch))        /* number */
  250.     get_number();
  251.     else if (ch == '"')            /* string */
  252.     get_string();
  253.     else if (get_rel())            /* relational operator */
  254.     ;
  255.     else                /* single character token */
  256.     dbv_token = getch();
  257.  
  258.     /* save the lookahead token */
  259.     savetkn = dbv_token;
  260.  
  261.     /* return the token */
  262.     return (dbv_token);
  263. }
  264.  
  265. /* db_ntoken - get next token (after skipping the current one) */
  266. int db_ntoken()
  267. {
  268.     /* get the current token */
  269.     db_token();
  270.  
  271.     /* make sure another is read on next call */
  272.     savetkn = 0;
  273.  
  274.     /* return the current token */
  275.     return (dbv_token);
  276. }
  277.  
  278. /* db_xntoken - get next token (after skipping the current one) */
  279. int db_xntoken()
  280. {
  281.     /* get the current token */
  282.     db_xtoken();
  283.  
  284.     /* make sure another is read on next call */
  285.     savetkn = 0;
  286.  
  287.     /* return the current token */
  288.     return (dbv_token);
  289. }
  290.  
  291. /* db_scmp - compare two strings */
  292. int db_scmp(str1,str2)
  293.   char *str1,*str2;
  294. {
  295.     if (dbv_fold)
  296.         return (scmp(str1,str2));
  297.     else
  298.         return (strcmp(str1,str2));
  299. }
  300.  
  301. /* db_sncmp - compare two strings with a maximum length */
  302. int db_sncmp(str1,str2,len)
  303.   char *str1,*str2; int len;
  304. {
  305.     if (dbv_fold)
  306.         return (sncmp(str1,str2,len));
  307.     else
  308.         return (strncmp(str1,str2,len));
  309. }
  310.  
  311. /* scmp - compare two strings with alpha case folding */
  312. static int scmp(str1,str2)
  313.   char *str1,*str2;
  314. {
  315.     int ch1,ch2;
  316.  
  317.     /* compare each character */
  318.     while (*str1 && *str2) {
  319.  
  320.         /* fold the character from the first string */
  321.         if (isupper(*str1))
  322.             ch1 = tolower(*str1++);
  323.         else
  324.             ch1 = *str1++;
  325.  
  326.         /* fold the character from the second string */
  327.         if (isupper(*str2))
  328.             ch2 = tolower(*str2++);
  329.         else
  330.             ch2 = *str2++;
  331.  
  332.         /* compare the characters */
  333.         if (ch1 != ch2)
  334.             if (ch1 < ch2)
  335.             return (-1);
  336.             else
  337.             return (1);
  338.     }
  339.  
  340.     /* check for strings of different lengths */
  341.     if (*str1 == *str2)
  342.         return (0);
  343.     else if (*str1 == 0)
  344.         return (-1);
  345.     else
  346.         return (1);
  347. }
  348.  
  349. /* sncmp - compare two strings with alpha case folding and a maximum length */
  350. static int sncmp(str1,str2,len)
  351.   char *str1,*str2; int len;
  352. {
  353.     int ch1,ch2;
  354.  
  355.     /* compare each character */
  356.     while (*str1 && *str2 && len > 0) {
  357.  
  358.         /* fold the character from the first string */
  359.         if (isupper(*str1))
  360.             ch1 = tolower(*str1++);
  361.         else
  362.             ch1 = *str1++;
  363.  
  364.         /* fold the character from the second string */
  365.         if (isupper(*str2))
  366.             ch2 = tolower(*str2++);
  367.         else
  368.             ch2 = *str2++;
  369.  
  370.         /* compare the characters */
  371.         if (ch1 != ch2)
  372.             if (ch1 < ch2)
  373.             return (-1);
  374.             else
  375.             return (1);
  376.  
  377.         /* decrement the string length */
  378.         len--;
  379.     }
  380.  
  381.     /* check for strings of different lengths */
  382.     if (len == 0 || *str1 == *str2)
  383.         return (0);
  384.     else if (*str1 == 0)
  385.         return (-1);
  386.     else
  387.         return (1);
  388. }
  389.  
  390. /* get_id - get a keyword or a user identifier */
  391. static get_id()
  392. {
  393.     int ch,nchars,i;
  394.     
  395.     /* input letters and digits */
  396.     ch = nextch();
  397.     nchars = 0;
  398.     while (isalpha(ch) || isdigit(ch)) {
  399.     if (nchars < KEYWORDMAX)
  400.         dbv_tstring[nchars++] = ch;
  401.     getch(); ch = thisch();
  402.     }
  403.  
  404.     /* terminate the keyword */
  405.     dbv_tstring[nchars] = EOS;
  406.  
  407.     /* assume its an identifier */
  408.     dbv_token = ID;
  409.  
  410.     /* check for keywords */
  411.     for (i = 0; keywords[i] != NULL; i++)
  412.         if (db_scmp(dbv_tstring,keywords[i]) == 0)
  413.             dbv_token = keytokens[i];
  414. }
  415.  
  416. /* get_number - get a number */
  417. static get_number()
  418. {
  419.     int ch,ndigits,nodot;
  420.     
  421.     /* read digits and at most one decimal point */
  422.     ch = nextch();
  423.     ndigits = 0; nodot = TRUE;
  424.     while (isdigit(ch) || (nodot && ch == '.')) {
  425.         if (ch == '.')
  426.             nodot = FALSE;
  427.     if (ndigits < NUMBERMAX)
  428.         dbv_tstring[ndigits++] = ch;
  429.     getch(); ch = thisch();
  430.     }
  431.  
  432.     /* terminate the number */
  433.     dbv_tstring[ndigits] = EOS;
  434.  
  435.     /* get the value of the number */
  436.     sscanf(dbv_tstring,"%d",&dbv_tvalue);
  437.  
  438.     /* token is a number */
  439.     dbv_token = NUMBER;
  440. }
  441.  
  442. /* get_string - get a string */
  443. static get_string()
  444. {
  445.     int ch,nchars;
  446.     
  447.     /* skip the opening quote */
  448.     getch();
  449.  
  450.     /* read characters until a closing quote is found */
  451.     ch = thisch();
  452.     nchars = 0;
  453.     while (ch && ch != '"') {
  454.     if (nchars < STRINGMAX)
  455.         dbv_tstring[nchars++] = ch;
  456.     getch(); ch = thisch();
  457.     }
  458.  
  459.     /* terminate the string */
  460.     dbv_tstring[nchars] = EOS;
  461.  
  462.     /* skip the closing quote */
  463.     getch();
  464.  
  465.     /* token is a string */
  466.     dbv_token = STRING;
  467. }
  468.  
  469. /* get_rel - get a relational operator */
  470. static int get_rel()
  471. {
  472.     int ch;
  473.  
  474.     switch (ch = nextch()) {
  475.     case '=':
  476.             getch();
  477.         dbv_token = EQL;
  478.         return (TRUE);;
  479.     case '<':
  480.         getch(); ch = nextch();
  481.         if (ch == '>') {
  482.         getch();
  483.         dbv_token = NEQ;
  484.         }
  485.         else if (ch == '=') {
  486.         getch();
  487.         dbv_token = LEQ;
  488.         }
  489.         else
  490.         dbv_token = LSS;
  491.         return (TRUE);;
  492.     case '>':
  493.         getch(); ch = nextch();
  494.         if (ch == '=') {
  495.         getch();
  496.         dbv_token = GEQ;
  497.         }
  498.         else
  499.         dbv_token = GTR;
  500.         return (TRUE);;
  501.     default:
  502.         return (FALSE);
  503.     }
  504. }
  505.  
  506. /* getch - get the next character */
  507. static int getch()
  508. {
  509.     char fname[STRINGMAX+1];
  510.     int ch,i;
  511.  
  512.     /* return the lookahead character if there is one */
  513.     if (savech != EOS) {
  514.         ch = savech;
  515.         savech = EOS;
  516.         return (ch);
  517.     }
  518.  
  519.     /* get a character */
  520.     ch = getchx();
  521.  
  522.     /* skip spaces at the beginning of a command */
  523.     if (atbol && iprompt != NULL)
  524.         while (ch <= ' ')
  525.             ch = getchx();
  526.  
  527.     /* use continuation prompt next time */
  528.     iprompt = NULL;
  529.  
  530.     /* check for indirect command file */
  531.     while (ch == '@') {
  532.         for (i = 0; (savech = getchx()) > ' '; )
  533.             if (i < STRINGMAX)
  534.             fname[i++] = savech;
  535.         fname[i] = 0;
  536.         if (db_ifile(fname) != TRUE)
  537.             printf("*** error opening command file: %s ***\n",fname);
  538.         ch = getchx();
  539.     }
  540.  
  541.     /* return the character */
  542.     return (ch);
  543. }
  544.  
  545. /* getchx - get the next character */
  546. static int getchx()
  547. {
  548.     struct ifile *old_ifp;
  549.     int ch;
  550.  
  551.     /* check for input from buffer */
  552.     if (lptr != NULL) {
  553.         while (*lptr == EOS)
  554.             if (dbv_ifp != NULL)
  555.             if (dbv_ifp->if_mtext == NULL) {
  556.                 old_ifp = dbv_ifp;
  557.                 ch = dbv_ifp->if_savech; savech = EOS;
  558.                 lptr = dbv_ifp->if_lptr;
  559.                 dbv_ifp = dbv_ifp->if_next;
  560.                 free(old_ifp);
  561.                 if (ch != EOS)
  562.                 return (ch);
  563.                 if (lptr == NULL)
  564.                 break;
  565.             }
  566.             else {
  567.                 lptr = dbv_ifp->if_mtext->mt_text;
  568.                 dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
  569.             }
  570.             else
  571.             return (EOS);
  572.  
  573.         if (lptr != NULL)
  574.             return (*lptr++);
  575.     }
  576.  
  577.     /* print prompt if necessary */
  578.     if (atbol && dbv_ifp == NULL)
  579.         if (iprompt != NULL)
  580.             printf("%s",iprompt);
  581.         else if (cprompt != NULL)
  582.             printf("%s",cprompt);
  583.  
  584.     if (dbv_ifp == NULL)
  585.         if ((ch = getc(stdin)) == '\n')
  586.             atbol = TRUE;
  587.         else
  588.             atbol = FALSE;
  589.     else {
  590.         if ((ch = getc(dbv_ifp->if_fp)) == -1) {
  591.             old_ifp = dbv_ifp;
  592.             ch = dbv_ifp->if_savech; savech = EOS;
  593.             lptr = dbv_ifp->if_lptr;
  594.             dbv_ifp = dbv_ifp->if_next;
  595.             fclose(old_ifp->if_fp);
  596.             free(old_ifp);
  597.         }
  598.     }
  599.  
  600.     /* return the character */
  601.     return (ch);
  602. }
  603.  
  604. /* thisch - get the current character */
  605. static int thisch()
  606. {
  607.     /* get a lookahead character */
  608.     if (savech == EOS)
  609.         savech = getch();
  610.  
  611.     /* return lookahead character */
  612.     return (savech);
  613. }
  614.  
  615. /* nextch - get the next non-blank character */
  616. static int nextch()
  617. {
  618.     int ch;
  619.  
  620.     /* skip blank characters */
  621.     while ((ch = thisch()) <= ' ' && ch != EOS)
  622.         getch();
  623.  
  624.     /* return the first non-blank */
  625.     return (ch);
  626. }
  627.